#ifndef _STDARG_H
#define _STDARG_H

typedef char *va_list;		// 定义va_list 是一个字符指针类型。

/* Amount of space required in an argument list for an arg of type TYPE.
TYPE may alternatively be an expression whose type is used. */
/* 下面给出了类型为TYPE 的arg 参数列表所要求的空间容量。
TYPE 也可以是使用该类型的一个表达式 */

// 下面这句定义了取整后的TYPE 类型的字节长度值。是int 长度(4)的倍数。
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))

// 下面这个函数（用宏实现）使AP 指向传给函数的可变参数表的第一个参数。
// 在第一次调用va_arg 或va_end 之前，必须首先调用该函数。
// 17 行上的__builtin_saveregs()是在gcc 的库程序libgcc2.c 中定义的，用于保存寄存器。
// 它的说明可参见gcc 手册章节“Target Description Macros”中的
// “Implementing the Varargs Macros”小节。
#ifndef __sparc__
// int printk(const char *fmt, ...)
// {
// 	va_list args;
// 	int i;

// 	va_start(args, fmt);
// 	i=vsprintf(buf,fmt,args);
// 展开后，是将args = &fmt + fmt的大小，并且要转换指向成下一个栈单元位置
// 所以，args实际上取的是下一个参数的地址
#define va_start(AP, LASTARG) 						\
 (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#else

#define va_start(AP, LASTARG) 						\
 (__builtin_saveregs (),						\
  AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
#endif

// end好像不需要怎么做，因为上面定义该变量时，只是定义了一个局部变量
void va_end (va_list);		/* Defined in gnulib */

#define va_end(AP)

// 使用：va_arg(args, int)，后面接各种类型
// 将ap的指针再往高地址增加，指向下一人参数，同时再取之前位置的值。做一下转换。
#define va_arg(AP, TYPE)						\
 (AP += __va_rounded_size (TYPE),					\
  *((TYPE *) (AP - __va_rounded_size (TYPE))))

#endif /* _STDARG_H */
